package com.mzj.saas.mservice.bill.service;

import com.alibaba.fastjson.JSON;
import com.mzj.saas.commons.*;
import com.mzj.saas.commons.enums.BusinessTypeEnum;
import com.mzj.saas.commons.vo.redis.TokenRedisVo;
import com.mzj.saas.mservice.bill.entity.*;
import com.mzj.saas.mservice.bill.repository.*;
import com.mzj.saas.mservice.bill.vo.*;
import com.mzj.saas.mservice.community.entity.Community;
import com.mzj.saas.mservice.community.entity.CommunityBuild;
import com.mzj.saas.mservice.community.entity.CommunityBuildUnit;
import com.mzj.saas.mservice.community.repository.CommunityBuildRepository;
import com.mzj.saas.mservice.community.repository.CommunityBuildUnitRepository;
import com.mzj.saas.mservice.community.repository.CommunityRepository;
import com.mzj.saas.mservice.community.service.AppCommunityService;
import com.mzj.saas.mservice.eligible.entity.DepartmentHierarchy;
import com.mzj.saas.mservice.eligible.repository.DepartmentHierarchyRepository;
import com.mzj.saas.mservice.house.entity.House;
import com.mzj.saas.mservice.house.repository.HouseRepository;
import com.mzj.saas.mservice.propertybill.service.WithDrawService;
import com.mzj.saas.mservice.sys.entity.AppUser;
import com.mzj.saas.mservice.sys.entity.User;
import com.mzj.saas.mservice.sys.repository.AppUserRepository;
import com.mzj.saas.mservice.sys.repository.UserRepository;
import com.mzj.saas.mservice.sys.utils.SqlUtils;
import com.mzj.saas.redis.RedisService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class BillService {
    private static final Logger LOG = LoggerFactory.getLogger(BillService.class);
    @Autowired
    private JdbcTemplate jdbcTemplate;
    @Autowired
    private RedisService redisService;
    @Autowired
    private DepartmentHierarchyRepository departmentHierarchyRepository;
    @Autowired
    private HouseRepository houseRepository;
    @Autowired
    private CommunityRepository communityRepository;
    @Autowired
    private CommunityBuildRepository communityBuildRepository;
    @Autowired
    private CommunityBuildUnitRepository communityBuildUnitRepository;
    @Autowired
    private UserRepository userRepository;
    @Autowired
    private AppUserRepository appUserRepository;
    @Autowired
    private HouseWaitPaymentDetailRepository houseWaitPaymentDetailRepository;
    @Autowired
    private ExpenseBillRepository expenseBillRepository;
    @Autowired
    private HouseExpenseRuleRefRepository houseExpenseRuleRefRepository;
    @Autowired
    private HouseExpenseBillRuleRepository houseExpenseBillRuleRepository;
    @Autowired
    private HouseExpenseRentRepository houseExpenseRentRepository;
    @Autowired
    private HouseExpenseOtherRepository houseExpenseOtherRepository;
    @Autowired
    private HouseExpenseHouseRepository houseExpenseHouseRepository;
    @Autowired
    private HouseExpenseWaterRepository houseExpenseWaterRepository;
    @Autowired
    private HouseExpenseElectricRepository houseExpenseElectricRepository;
    @Autowired
    private HouseExpenseGasRepository houseExpenseGasRepository;
    @Autowired
    private AppCommunityService appCommunityService;
    @Autowired
    private RentBillRepository rentBillRepository;
    @Autowired
    private HousePaymentOrderRelationRepository housePaymentOrderRelationRepository;
    @Autowired
    private HousePaymentOrderRepository housePaymentOrderRepository;
    @Autowired
    private WithDrawService withDrawService;

    /**
     * 费用列表-列表信息显示
     *
     * @param accessToken 权限鉴定
     * @param pageNumber  当前页
     * @param pageSize    每页显示数量
     * @param type        类型标识 0全部账单 1未审核账单 2未缴费账单 3 已缴费账单
     * @param filter      费用列表筛查帮助类
     * @return
     */
    public ResultBean<Object> billListShow(String accessToken, Integer pageNumber, Integer pageSize, Integer type, BillSearchRequestVO filter) {
        //记录操作日志
        LOG.info("BillService billListShow accessToken={},pageNumber={},pageSize={},type={}", accessToken, pageNumber, pageSize, type);
        //默认返回成功
        ResultBean<Object> result = new ResultBean<>();
        result.setMsg(StatusCode.SUCCESS_CODE_10000.getErrorMsg());
        result.setCode(StatusCode.SUCCESS_CODE_10000.getErrorCode());
        //获取用户登录权限
        TokenRedisVo tokenRedisVo = redisService.findTokenVo(accessToken);
        ApiData<Map<String, Object>> apiData = new ApiData<>();
        try {
            //用户权限的鉴定
            if (tokenRedisVo == null) {
                result.setCode(StatusCode.ERROR_CODE_40001.getErrorCode());
                result.setMsg(StatusCode.ERROR_CODE_40001.getErrorMsg());
                return result;
            }

            String billSql = "SELECT  b.`id`,b.`house_id` AS houseId,b.`community_id` AS communityId,a1.name AS name1,a2.name AS name2,b.`building_num` AS buildingNum,"
                    + "b.`unit`,b.`room_number` AS roomNumber,b.`org_id` AS orgId,b.`match_user_id` AS matchUserId,b.`charge_type` AS chargeType,"
                    + "b.`measure_unit` AS measureUnit,b.`cost`, b.`start_time`  AS startTime, b.`end_time` AS endTime, b.`audit_status` AS auditStatus,"
                    + "b.`payment_status`  AS paymentStatus,b.`payment_time` AS paymentTime,b.`payment_channel` AS paymentChannel,"
                    + "b.`operator_id` AS operatorId,b.`last_update_time` AS lastUpdateTime,b.`create_time` AS createTime,b.should_pay_time AS shouldPayTime "
                    + "FROM `saas_expense_bill` b "
                    + "LEFT JOIN  `saas_app_user` a1  ON a1.`id` = b.match_user_id "
                    + "LEFT JOIN  `saas_app_user` a2  ON a2.`enterprise_user_id` = b.match_user_id "
                    + "WHERE 1=1 \n";

            List<Object> args = new ArrayList<>();
            StringBuilder where = new StringBuilder();

            //权限过滤
            List<Map<String, Object>> communityList = appCommunityService.findCommunity(accessToken).getResultData();
            if (communityList != null && !communityList.isEmpty()) {
                where.append(" and b.community_id in " + SqlUtils.foreachIn(communityList.size()));
                List<String> communityIds = communityList.stream().map(map -> {
                    String comId = map.get("communityId").toString();
                    return comId;
                }).collect(Collectors.toList());
                args.addAll(communityIds);
            } else {
                where.append(" and b.community_id in (null)");
            }
            //判断类型标识 0全部账单 1未审核账单 2未缴费账单 3 已缴费账单
            if (type != 0) {
                switch (type) {
                    case 1:
                        billSql += "  AND b.audit_status=0";
                        break;
                    case 2:
                        billSql += "  AND b.audit_status = 1 and b.payment_status = 0";
                        break;
                    case 3:
                        billSql += "  AND b.payment_status=1";
                        break;
                }
            }

            String offsets = "   LIMIT ? OFFSET ? ";
            //判断数据是否为空
            if (StringUtils.isNotBlank(filter.getHouseId())) {
                where.append("  AND  b.`house_id` = ?  \n");
                args.add(filter.getHouseId());
            }
            if (StringUtils.isNotBlank(filter.getCommunityId())) {
                where.append("  AND  b.`community_id` = ?  \n");
                args.add(filter.getCommunityId());
            }
            if (filter.getBuildingNum() != null) {
                where.append("  AND  b.`building_num` =  ?  \n");
                args.add(filter.getBuildingNum());
            }
            if (filter.getUnit() != null) {
                where.append("  AND  b.`unit` =  ?  \n");
                args.add(filter.getUnit());
            }
            if (StringUtils.isNotBlank(filter.getRoomNumber())) {
                where.append("  AND  b.`room_number` = ?  \n");
                args.add(filter.getRoomNumber());
            }
            if (filter.getOrgId() != null) {
                where.append("  AND  b.`org_id` =  ?  \n");
                args.add(filter.getOrgId());
            }
            if (StringUtils.isNotBlank(filter.getMatchUserName())) {
                where.append("  AND  (a1.`name` = ? or a2.`name` = ?) \n");
                args.add("%" + filter.getMatchUserName() + "%");
                args.add("%" + filter.getMatchUserName() + "%");
            }
            if (filter.getChargeType() != null) {
                where.append("  AND  b.`charge_type` =  ?  \n");
                args.add(filter.getChargeType());
            }
            if (filter.getPaymentStatus() != null) {
                where.append("  AND  b.`payment_status` =  ?  \n");
                args.add(filter.getPaymentStatus());
            }

            // 查询总记录数
            String count = "select count(1) FROM (" + billSql + where + ") c  ";
            Long total = jdbcTemplate.queryForObject(count, Long.class, args.toArray());
            LOG.info("SQL :" + billSql + where);
            if (total == 0) {
                result.setCode(StatusCode.SUCCESS_CODE_10000.getErrorCode());
                result.setMsg(StatusCode.SUCCESS_CODE_10000.getErrorMsg());
                result.setResultData(null);
                return result;
            }

            // 查询分页数据
            where.append("  ORDER BY ").append(" b.create_time,b.id desc ").append(" \n").append(offsets);
            args.add(pageSize);
            args.add(pageNumber * pageSize);
            List<Map<String, Object>> peopleList = jdbcTemplate.queryForList(billSql + where, args.toArray());
            for (Map<String, Object> map : peopleList) {
                Long id = Long.valueOf(String.valueOf(map.get("id")));
                String communityId = String.valueOf(map.get("communityId"));
                Long buildingNum = Long.valueOf(String.valueOf(map.get("buildingNum")));
                Long unit = Long.valueOf(String.valueOf(map.get("unit")));
                Long orgId = Long.valueOf(String.valueOf(map.get("orgId")));
                String matchUserId = String.valueOf(map.get("matchUserId"));
                Integer chargeType = Integer.valueOf(String.valueOf(map.get("chargeType")));
                String cost = fenToYuan(String.valueOf(map.get("cost")));
                map.put("cost", cost);
                Optional<Community> communityOptional = communityRepository.findById(communityId);
                //获取小区名称
                if (communityOptional.isPresent()) {
                    Community community = communityOptional.get();
                    map.put("communityName", community.getName());
                }
                //获取楼栋名称
                Optional<CommunityBuild> communityBuildOptional = communityBuildRepository.findById(buildingNum);
                if (communityBuildOptional.isPresent()) {
                    CommunityBuild communityBuild = communityBuildOptional.get();
                    map.put("buildingNumName", communityBuild.getName());
                }
                //获取单元名称
                Optional<CommunityBuildUnit> communityBuildUnitOptional = communityBuildUnitRepository.findById(unit);
                if (communityBuildUnitOptional.isPresent()) {
                    CommunityBuildUnit communityBuildUnit = communityBuildUnitOptional.get();
                    map.put("unitName", communityBuildUnit.getName());
                }
                //获取产权单位名称
                DepartmentHierarchy propertyUnit = departmentHierarchyRepository.findByOrgId(orgId);
                if (propertyUnit != null) {
                    map.put("orgName", propertyUnit.getName());
                }
                //获取承租人名称、手机号
                //User lesseeUser = userRepository.findById(matchUserId);
                AppUser lesseeUser = appUserRepository.findByIdOrEnterpriseUserId(matchUserId, matchUserId);
                if (lesseeUser != null) {
                    map.put("matchUserName", lesseeUser.getName());
                    map.put("matchUserPhone", lesseeUser.getPhone());
                    map.put("name", lesseeUser.getName());
                }
                HouseWaitPaymentDetail houseWaitPaymentDetail = houseWaitPaymentDetailRepository.findByExpenseBillIdAndChargeType(id, chargeType);
                map.put("waitPaymentDetailId", houseWaitPaymentDetail.getId());
                switch (chargeType) {
                    case 1:
                        map.put("chargeTypeName", "水费");
                        map.put("chargeTypeUnit", fenToYuan(String.valueOf(houseWaitPaymentDetail.getWaterUnitPrice())));
                        //map.put("chargeTypeUseNumber", houseWaitPaymentDetail.getWaterUsage() + "吨");
                        map.put("startNum", houseWaitPaymentDetail.getWaterStartNum());
                        map.put("endNum", houseWaitPaymentDetail.getWaterEndNum());
                        map.put("usage", houseWaitPaymentDetail.getWaterUsage());
                        break;
                    case 2:
                        map.put("chargeTypeName", "电费");
                        map.put("chargeTypeUnit", fenToYuan(String.valueOf(houseWaitPaymentDetail.getElectricUnitPrice())));
                        //map.put("chargeTypeUseNumber", houseWaitPaymentDetail.getElectricUsage() + "度");
                        map.put("startNum", houseWaitPaymentDetail.getElectricStartNum());
                        map.put("endNum", houseWaitPaymentDetail.getElectricEndNum());
                        map.put("usage", houseWaitPaymentDetail.getElectricUsage());
                        break;
                    case 3:
                        map.put("chargeTypeName", "物业费");
                        break;
                    case 4:
                        map.put("chargeTypeName", "宽带费");
                        break;
                    case 5:
                        map.put("chargeTypeName", "电视费");
                        break;
                    case 6:
                        map.put("chargeTypeName", "燃气费");
                        map.put("chargeTypeUnit", fenToYuan(String.valueOf(houseWaitPaymentDetail.getGasUnitPrice())));
                        map.put("startNum", houseWaitPaymentDetail.getGasStartNum());
                        map.put("endNum", houseWaitPaymentDetail.getGasEndNum());
                        map.put("usage", houseWaitPaymentDetail.getGasUsage());
                        break;
                    case 7:
                        map.put("chargeTypeName", "暖气费");
                        break;
                }
            }
            //设置数据
            apiData.setData(peopleList);
            apiData.setTotal(total);
            LOG.info("SQL :" + billSql + where);
            //把数据返回给前端页面
            result.setResultData(apiData);
        } catch (Exception e) {
            LOG.error(e.getMessage(), e);
            result.setCode(StatusCode.ERROR_CODE_10001.getErrorCode());
            result.setMsg(e.getMessage());
        }
        return result;
    }

    /*
     *编辑账单
     */
    public ResultBean<Object> editBill(String accessToken, EditBillRequestVO vo) {
        try {
            TokenRedisVo tokenRedisVo = redisService.findTokenVo(accessToken);
            if (tokenRedisVo == null) {
                return ResultBean.failedResultOfToken();
            }

            if (vo.getId() == null || vo.getBeginNum() == null
                    || vo.getEndNum() == null || vo.getCost() == null) {
                return ResultBean.failedResultOfParamWithMsg("参数错误");
            }

            Optional<ExpenseBill> expenseBillOptional = expenseBillRepository.findById(vo.getId());
            if (!expenseBillOptional.isPresent()) {
                return ResultBean.failedResultWithMsg("账单信息不存在");
            }
            ExpenseBill expenseBill = expenseBillOptional.get();
            Integer chargeType = expenseBill.getChargeType();

            List<HouseWaitPaymentDetail> billDetails = houseWaitPaymentDetailRepository.findByExpenseBillId(vo.getId());
            if (billDetails.isEmpty()) {
                return ResultBean.failedResultWithMsg("账单信息不存在");
            }
            HouseWaitPaymentDetail billDetail = billDetails.get(0);

            //获取前一个账单
            String sql = "SELECT d.* FROM saas_expense_bill b  \n" +
                    "JOIN saas_house_wait_payment_detail d ON b.id = d.expense_bill_id \n" +
                    "WHERE b.house_id = ? AND b.charge_type = ? AND b.audit_status = 1  \n" +
                    "AND b.match_user_id IS NOT NULL AND b.id != ?\n" +
                    "ORDER BY b.create_time DESC LIMIT 1";
            ArrayList<Object> args = new ArrayList<>();
            args.add(expenseBill.getHouseId());
            args.add(expenseBill.getChargeType());
            args.add(expenseBill.getId());
            List<Map<String, Object>> upBills = jdbcTemplate.queryForList(sql, args.toArray());
            if (!upBills.isEmpty()) {
                //当前账单起数必须大于前一个订单止数
                Map<String, Object> map = upBills.get(0);
                Integer endNum = null;
                switch (chargeType) {
                    case 1:
                        endNum = Integer.parseInt(map.get("water_end_num").toString());
                        break;
                    case 2:
                        endNum = Integer.parseInt(map.get("electric_end_num").toString());
                        break;
                    case 6:
                        endNum = Integer.parseInt(map.get("gas_end_num").toString());
                        break;
                }
                if (vo.getBeginNum() <= endNum) {
                    return ResultBean.failedResultWithMsg("账单起数必须大于前一个订单止数");
                }
            }

            expenseBill.setCost(ConvertUtils.yuan2fen(vo.getCost()));
            expenseBillRepository.save(expenseBill);

            switch (chargeType) {
                case 1:
                    billDetail.setWaterStartNum(vo.getBeginNum());
                    billDetail.setWaterEndNum(vo.getEndNum());
                    billDetail.setWaterUsage(vo.getEndNum() - vo.getBeginNum());
                    break;
                case 2:
                    billDetail.setElectricStartNum(vo.getBeginNum());
                    billDetail.setElectricEndNum(vo.getEndNum());
                    billDetail.setElectricUsage(vo.getEndNum() - vo.getBeginNum());
                    break;
                case 6:
                    billDetail.setGasStartNum(vo.getBeginNum());
                    billDetail.setGasEndNum(vo.getEndNum());
                    billDetail.setGasUsage(vo.getEndNum() - vo.getBeginNum());
                    break;
            }
            houseWaitPaymentDetailRepository.save(billDetail);

            return ResultBean.successfulResult(null);
        } catch (Exception e) {
            LOG.error(e.getMessage(), e);
            return ResultBean.failedResultOfException();
        }
    }

    /**
     * 审核
     * @param accessToken
     * @param ids
     * @return
     * 修改账单审核状态  账单数据信息 收费项目数据必须不为空
     */
    public ResultBean<Object> examineBill(String accessToken, List<Long> ids) {
        LOG.info("BillService examineBill accessToken={},ids={}", accessToken, JSON.toJSONString(ids));
        ResultBean<Object> result = new ResultBean<>();
        result.setMsg(StatusCode.SUCCESS_CODE_10000.getErrorMsg());
        result.setCode(StatusCode.SUCCESS_CODE_10000.getErrorCode());
        TokenRedisVo tokenRedisVo = redisService.findTokenVo(accessToken);

        try {
            if (tokenRedisVo == null) {
                result.setCode(StatusCode.ERROR_CODE_40001.getErrorCode());
                result.setMsg(StatusCode.ERROR_CODE_40001.getErrorMsg());
                return result;
            }

            if (ids == null || ids.size() == 0) {
                return ResultBean.failedResultWithMsg("账单id为空");
            }

            Date date = new Date();

            List<ExpenseBill> expenseBills = expenseBillRepository.findByIdIn(ids);
            for (ExpenseBill expenseBill : expenseBills) {
                List<HouseWaitPaymentDetail> billDetails = houseWaitPaymentDetailRepository.findByExpenseBillId(expenseBill.getId());
                if (billDetails.isEmpty()) {
                    return ResultBean.failedResultWithMsg("账单数据有误");
                }
                HouseWaitPaymentDetail billDetail = billDetails.get(0);

                Integer chargeType = expenseBill.getChargeType();
                switch (chargeType) {
                    case 1:
                        if (expenseBill.getCost() == null || billDetail.getWaterStartNum() == null || billDetail.getWaterEndNum() == null) {
                            return ResultBean.failedResultWithMsg("有账单需完善信息，无法审核");
                        }
                        break;
                    case 2:
                        if (expenseBill.getCost() == null || billDetail.getElectricStartNum() == null || billDetail.getElectricEndNum() == null) {
                            return ResultBean.failedResultWithMsg("有账单需完善信息，无法审核");
                        }
                        break;
                    case 6:
                        if (expenseBill.getCost() == null || billDetail.getGasStartNum() == null || billDetail.getGasEndNum() == null) {
                            return ResultBean.failedResultWithMsg("有账单需完善信息，无法审核");
                        }
                        break;
                }

                expenseBill.setAuditStatus(1);//已审核
                expenseBill.setOperatorId(tokenRedisVo.getId());
                expenseBill.setLastUpdateTime(date);
            }
            expenseBillRepository.saveAll(expenseBills);

        } catch (Exception e) {
            LOG.error(e.getMessage(), e);
            result.setCode(StatusCode.ERROR_CODE_10001.getErrorCode());
            result.setMsg(e.getMessage());
        }
        return result;
    }
    /**
     * 费用列表-设置
     * @param accessToken 权限鉴定
     * @param vo 编辑账单请求帮助类
     * @return
     */
    public ResultBean<Object> setupBill(String accessToken, EditBillRequestVO vo) {
        try {
            TokenRedisVo tokenRedisVo = redisService.findTokenVo(accessToken);
            if (tokenRedisVo == null) {
                return ResultBean.failedResultOfToken();
            }

            if (vo.getId() == null || vo.getChargeType() == null || vo.getPaymentChannel() == null) {
                return ResultBean.failedResultOfParamWithMsg("参数错误");
            }

            Date date = new Date();

            Optional<ExpenseBill> ExpenseBillOptional = expenseBillRepository.findById(vo.getId());
            if (!ExpenseBillOptional.isPresent()) {
                return ResultBean.failedResultWithMsg("账单信息不存在");
            }
            ExpenseBill expenseBill = ExpenseBillOptional.get();
            expenseBill.setPaymentStatus(1);
            expenseBill.setPaymentTime(date);
            expenseBill.setPaymentChannel(vo.getPaymentChannel());
            expenseBill.setOperatorId(tokenRedisVo.getId());
            expenseBill.setLastUpdateTime(date);
            expenseBillRepository.save(expenseBill);

            //生成支付记录
            String orderNumber = String.valueOf(KeyWorker.nextId());
            HousePaymentOrderRelation por = new HousePaymentOrderRelation();
            por.setBillId(vo.getId());
            por.setOrderNumber(orderNumber);
            por.setPlatformCommissionAmount(0);
            por.setBillAmount(expenseBill.getCost());
            if (vo.getChargeType() == 1) {
                por.setBusinessType(BusinessTypeEnum.WATER_FEE.getValue());
            } else if (vo.getChargeType() == 2) {
                por.setBusinessType(BusinessTypeEnum.ELECTRIC_FEE.getValue());
            } else if (vo.getChargeType() == 3) {
                por.setBusinessType(BusinessTypeEnum.PROPERTY_FEE.getValue());
            } else if (vo.getChargeType() == 4) {
                por.setBusinessType(BusinessTypeEnum.BROADBAND_FEE.getValue());
            } else if (vo.getChargeType() == 5) {
                por.setBusinessType(BusinessTypeEnum.TV_FEE.getValue());
            } else if (vo.getChargeType() == 6) {
                por.setBusinessType(BusinessTypeEnum.COALGAS_FEE.getValue());
            } else if (vo.getChargeType() == 7) {
                por.setBusinessType(BusinessTypeEnum.HEATING_FEE.getValue());
            } else if (vo.getChargeType() == 10) {
                // 退租
                por.setBusinessType(BusinessTypeEnum.OTHER_FEE.getValue());
            }
            housePaymentOrderRelationRepository.save(por);

            HousePaymentOrder paymentOrder = new HousePaymentOrder();
            paymentOrder.setOrderNumber(orderNumber);
            paymentOrder.setBillAmount(expenseBill.getCost());
            paymentOrder.setPlatformCommissionAmount(0);
            paymentOrder.setWxCommissionAmount(0);
            paymentOrder.setTotalAmount(expenseBill.getCost());
            paymentOrder.setPayUserId(expenseBill.getMatchUserId());
            paymentOrder.setPayResult(1);
            paymentOrder.setPayTime(date);
            housePaymentOrderRepository.save(paymentOrder);

            return ResultBean.successfulResult(null);
        } catch (Exception e) {
            LOG.error(e.getMessage(), e);
            return ResultBean.failedResultOfException();
        }
    }

    /**
     * 租金列表-列表信息展示
     *
     * @param accessToken 权限鉴定
     * @param pageNumber  当前页
     * @param pageSize    每页显示数量
     * @param type        type 0全部账单 1未缴费账单 2 已缴费账单
     * @param filter      费用列表筛查帮助类
     * @return
     */
    public ResultBean<Object> rentList(String accessToken, Integer pageNumber, Integer pageSize, Integer type, BillSearchRequestVO filter) {
        //记录操作日志
        LOG.info("BillService rentList accessToken={},pageNumber={},pageSize={},type={}", accessToken, pageNumber, pageSize, type);
        ResultBean<Object> result = new ResultBean<>();
        result.setMsg(StatusCode.SUCCESS_CODE_10000.getErrorMsg());
        result.setCode(StatusCode.SUCCESS_CODE_10000.getErrorCode());
        //获取用户登录权限
        TokenRedisVo tokenRedisVo = redisService.findTokenVo(accessToken);
        ApiData<Map<String, Object>> apiData = new ApiData<>();
        try {
            //用户权限的鉴定
            if (tokenRedisVo == null) {
                result.setCode(StatusCode.ERROR_CODE_40001.getErrorCode());
                result.setMsg(StatusCode.ERROR_CODE_40001.getErrorMsg());
                return result;
            }

            String billSql = "SELECT  b.`id`,b.`house_id` AS houseId,b.`community_id` AS communityId,a1.name AS name1,a2.name AS name2,b.`building_num` AS buildingNum,"
                    + "b.`unit`,b.`room_number` AS roomNumber,b.`org_id` AS orgId,b.`match_user_id` AS matchUserId,"
                    + "b.`charge_type` AS chargeType,b.`measure_unit` AS measureUnit,b.`cost`, b.`start_time`  AS startTime, "
                    + "b.`end_time` AS endTime,b.`payment_status`  AS paymentStatus,b.`payment_time` AS paymentTime,b.`payment_channel` AS paymentChannel,"
                    + "b.`create_time` AS createTime,b.audit_status as auditStatus, b.should_pay_time AS shouldPayTime  FROM `saas_rent_bill` b "
                    + "LEFT JOIN  `saas_app_user` a1  ON a1.`id` = b.match_user_id "
                    + "LEFT JOIN  `saas_app_user` a2  ON a2.`enterprise_user_id` = b.match_user_id "
                    + "WHERE 1=1 \n";

            List<Object> args = new ArrayList<>();
            StringBuilder where = new StringBuilder();

            //权限过滤
            List<Map<String, Object>> communityList = appCommunityService.findCommunity(accessToken).getResultData();
            if (communityList != null && !communityList.isEmpty()) {
                where.append(" and b.community_id in " + SqlUtils.foreachIn(communityList.size()));
                List<String> communityIds = communityList.stream().map(map -> {
                    String comId = map.get("communityId").toString();
                    return comId;
                }).collect(Collectors.toList());
                args.addAll(communityIds);
            } else {
                where.append(" and b.community_id in (null)");
            }

            if (type != 0) {
                switch (type) {
                    case 1:
                        billSql += "  AND b.audit_status = 1 and b.payment_status = 0";
                        break;
                    case 2:
                        billSql += "  AND b.payment_status=1";
                        break;
                }
            }

            String offsets = "   LIMIT ? OFFSET ? ";
            //判断参数是否为空
            if (StringUtils.isNotBlank(filter.getHouseId())) {
                where.append("  AND  b.`house_id` = ?  \n");
                args.add(filter.getHouseId());
            }
            if (StringUtils.isNotBlank(filter.getCommunityId())) {
                where.append("  AND  b.`community_id` = ?  \n");
                args.add(filter.getCommunityId());
            }
            if (filter.getBuildingNum() != null) {
                where.append("  AND  b.`building_num` =  ?  \n");
                args.add(filter.getBuildingNum());
            }
            if (filter.getUnit() != null) {
                where.append("  AND  b.`unit` =  ?  \n");
                args.add(filter.getUnit());
            }
            if (StringUtils.isNotBlank(filter.getRoomNumber())) {
                where.append("  AND  b.`room_number` = ?  \n");
                args.add(filter.getRoomNumber());
            }
            if (filter.getOrgId() != null) {
                where.append("  AND  b.`org_id` =  ?  \n");
                args.add(filter.getOrgId());
            }
            if (StringUtils.isNotBlank(filter.getMatchUserName())) {
                where.append("  AND  (a1.`name` like  ? or a2.`name` like  ?) \n");
                args.add("%" + filter.getMatchUserName() + "%");
                args.add("%" + filter.getMatchUserName() + "%");
            }
            if (filter.getChargeType() != null) {
                where.append("  AND  b.`charge_type` =  ?  \n");
                args.add(filter.getChargeType());
            }
            if (filter.getPaymentStatus() != null) {
                where.append("  AND  b.`payment_status` =  ?  \n");
                args.add(filter.getPaymentStatus());
            }

            // 查询总记录数
            String count = "select count(1) FROM (" + billSql + where + ") c  ";
            Long total = jdbcTemplate.queryForObject(count, Long.class, args.toArray());
            if (total == 0) {
                result.setCode(StatusCode.SUCCESS_CODE_10000.getErrorCode());
                result.setMsg(StatusCode.SUCCESS_CODE_10000.getErrorMsg());
                result.setResultData(null);
                return result;
            }

            // 查询分页数据
            where.append("  ORDER BY ").append(" b.create_time,b.id desc ").append(" \n").append(offsets);
            args.add(pageSize);
            args.add(pageNumber * pageSize);
            List<Map<String, Object>> peopleList = jdbcTemplate.queryForList(billSql + where, args.toArray());
            for (Map<String, Object> map : peopleList) {
                String communityId = String.valueOf(map.get("communityId"));
                Long buildingNum = Long.valueOf(String.valueOf(map.get("buildingNum")));
                Long unit = Long.valueOf(String.valueOf(map.get("unit")));
                Long orgId = Long.valueOf(String.valueOf(map.get("orgId")));
                String matchUserId = String.valueOf(map.get("matchUserId"));
                String cost = fenToYuan(String.valueOf(map.get("cost")));
                map.put("cost", cost);
                Optional<Community> communityOptional = communityRepository.findById(communityId);
                //获取小区名称
                if (communityOptional.isPresent()) {
                    Community community = communityOptional.get();
                    map.put("communityName", community.getName());
                }
                //获取楼栋名称
                Optional<CommunityBuild> communityBuildOptional = communityBuildRepository.findById(buildingNum);
                if (communityBuildOptional.isPresent()) {
                    CommunityBuild communityBuild = communityBuildOptional.get();
                    map.put("buildingNumName", communityBuild.getName());
                }
                //获取单元名称
                Optional<CommunityBuildUnit> communityBuildUnitOptional = communityBuildUnitRepository.findById(unit);
                if (communityBuildUnitOptional.isPresent()) {
                    CommunityBuildUnit communityBuildUnit = communityBuildUnitOptional.get();
                    map.put("unitName", communityBuildUnit.getName());
                }
                //获取产权单位名称
                DepartmentHierarchy propertyUnit = departmentHierarchyRepository.findByOrgId(orgId);
                if (propertyUnit != null) {
                    map.put("orgName", propertyUnit.getName());
                }
                //获取承租人名称、手机号
                //User lesseeUser = userRepository.findById(matchUserId);
                AppUser lesseeUser = appUserRepository.findByIdOrEnterpriseUserId(matchUserId, matchUserId);
                if (lesseeUser != null) {
                    map.put("matchUserName", lesseeUser.getName());
                    map.put("matchUserPhone", lesseeUser.getPhone());
                    map.put("name", lesseeUser.getName());
                }
            }

            apiData.setData(peopleList);
            apiData.setTotal(total);
            result.setResultData(apiData);
        } catch (Exception e) {
            LOG.error(e.getMessage(), e);
            result.setCode(StatusCode.ERROR_CODE_10001.getErrorCode());
            result.setMsg(e.getMessage());
        }
        return result;
    }
    /**
     * 租金列表-审核
     * @param accessToken 权限鉴定
     * @param ids 审批账单id集合
     * @return
     */
    public ResultBean<Object> examineRentBill(String accessToken, List<Long> ids) {
    	LOG.info("examineRentBill, ids={}", JSON.toJSONString(ids));
        ResultBean<Object> result = new ResultBean<>();
        result.setMsg(StatusCode.SUCCESS_CODE_10000.getErrorMsg());
        result.setCode(StatusCode.SUCCESS_CODE_10000.getErrorCode());
        TokenRedisVo tokenRedisVo = redisService.findTokenVo(accessToken);
        try {
            if (tokenRedisVo == null) {
                result.setCode(StatusCode.ERROR_CODE_40001.getErrorCode());
                result.setMsg(StatusCode.ERROR_CODE_40001.getErrorMsg());
                return result;
            }

            if (ids == null || ids.size() == 0) {
                return ResultBean.failedResultWithMsg("账单id为空");
            }

            List<RentBill> rentBills = rentBillRepository.findByIdIn(ids);
            for (RentBill rentBill : rentBills) {
                rentBill.setAuditStatus(1);
            }
            rentBillRepository.saveAll(rentBills);

        } catch (Exception e) {
            LOG.error(e.getMessage(), e);
            result.setCode(StatusCode.ERROR_CODE_10001.getErrorCode());
            result.setMsg(e.getMessage());
        }
        return result;
    }
    /**
     * 租金列表-设置
     * @param accessToken 权限鉴定
     * @param vo 编辑账单请求帮助类
     * @return
     */
    public ResultBean<Object> setupRentBill(String accessToken, EditBillRequestVO vo) {
        try {
            TokenRedisVo tokenRedisVo = redisService.findTokenVo(accessToken);
            if (tokenRedisVo == null) {
                return ResultBean.failedResultOfToken();
            }

            if (vo.getId() == null || vo.getChargeType() == null || vo.getPaymentChannel() == null) {
                return ResultBean.failedResultOfParamWithMsg("参数错误");
            }

            Date date = new Date();

            Optional<RentBill> rentBillOptional = rentBillRepository.findById(vo.getId());
            if (!rentBillOptional.isPresent()) {
                return ResultBean.failedResultWithMsg("账单信息不存在");
            }
            RentBill rentBill = rentBillOptional.get();
            rentBill.setPaymentStatus(1);
            rentBill.setPaymentTime(date);
            rentBill.setPaymentChannel(vo.getPaymentChannel());
            rentBillRepository.save(rentBill);

            //生成支付记录
            String orderNumber = String.valueOf(KeyWorker.nextId());
            HousePaymentOrderRelation por = new HousePaymentOrderRelation();
            por.setBillId(vo.getId());
            por.setOrderNumber(orderNumber);
            por.setPlatformCommissionAmount(0);
            por.setBillAmount(rentBill.getCost());
            if (vo.getChargeType() == 1) {
                por.setBusinessType(BusinessTypeEnum.RENT_FEE.getValue());
            } else if (vo.getChargeType() == 2) {
                por.setBusinessType(BusinessTypeEnum.DEPOSIT_FEE.getValue());
            }
            housePaymentOrderRelationRepository.save(por);

            HousePaymentOrder paymentOrder = new HousePaymentOrder();
            paymentOrder.setOrderNumber(orderNumber);
            paymentOrder.setBillAmount(rentBill.getCost());
            paymentOrder.setPlatformCommissionAmount(0);
            paymentOrder.setWxCommissionAmount(0);
            paymentOrder.setTotalAmount(rentBill.getCost());
            paymentOrder.setPayUserId(rentBill.getMatchUserId());
            paymentOrder.setPayResult(1);
            paymentOrder.setPayTime(date);
            housePaymentOrderRepository.save(paymentOrder);

            return ResultBean.successfulResult(null);
        } catch (Exception e) {
            LOG.error(e.getMessage(), e);
            return ResultBean.failedResultOfException();
        }
    }

    /*
     *元转换为分
     */
    private String yuanToFen(String amount) {
        NumberFormat format = NumberFormat.getInstance();
        try {
            Number number = format.parse(amount);
            double temp = number.doubleValue() * 100.0;
            format.setGroupingUsed(false);
            // 设置返回数的小数部分所允许的最大位数
            format.setMaximumFractionDigits(0);
            amount = format.format(temp);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return amount;
    }

    /*
     *分转换为元
     */
    private String fenToYuan(String amount) {
        NumberFormat format = NumberFormat.getInstance();
        try {
            Number number = format.parse(amount);
            double temp = number.doubleValue() / 100.0;
            format.setGroupingUsed(false);
            // 设置返回的小数部分所允许的最大位数
            format.setMaximumFractionDigits(2);
            amount = format.format(temp);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return amount;
    }

    /**
     * 账单生成-列表显示
     *
     * @param accessToken 权限鉴定
     * @param pageNumber  当前页
     * @param pageSize    页数
     * @param id          账单id
     * @return
     */
    public ResultBean<Object> createBillList(String accessToken, Integer pageNumber, Integer pageSize, String id, String community) {
        //记录操作日志
        LOG.info("BillService createBillList accessToken={},pageNumber={},pageSize={},id={},community={}", accessToken, pageNumber, pageSize, id, community);
        //默认返回成功
        ResultBean<Object> result = new ResultBean<>();
        result.setMsg(StatusCode.SUCCESS_CODE_10000.getErrorMsg());
        result.setCode(StatusCode.SUCCESS_CODE_10000.getErrorCode());
        TokenRedisVo tokenRedisVo = redisService.findTokenVo(accessToken);
        ApiData<Map<String, Object>> apiData = new ApiData<>();
        try {
            //用户权限的鉴定
            if (tokenRedisVo == null) {
                result.setCode(StatusCode.ERROR_CODE_40001.getErrorCode());
                result.setMsg(StatusCode.ERROR_CODE_40001.getErrorMsg());
                return result;
            }

            String billSql = "SELECT r.`id`,r.`community_id` AS communityId,r.name,r.`number`, r.`start_time` AS startTime,\n" +
                    "r.`end_time` AS endTime,r.`close_time` AS closeTime,r.`charge_type` AS chargeType,r.`operator_id` AS operatorId,\n" +
                    "r.`create_time` AS createTime FROM `saas_house_expense_bill_rule` r left join saas_house_expense_rule_ref rf on r.id=rf.rule_id WHERE 1=1 and r.type = 1  \n";
            List<Object> args = new ArrayList<>();
            StringBuilder where = new StringBuilder();

            //权限过滤
            List<Map<String, Object>> communityList = appCommunityService.findCommunity(accessToken).getResultData();
            if (communityList != null && !communityList.isEmpty()) {
                where.append(" and rf.community_id in " + SqlUtils.foreachIn(communityList.size()));
                List<String> communityIds = communityList.stream().map(map -> {
                    String comId = map.get("communityId").toString();
                    return comId;
                }).collect(Collectors.toList());
                args.addAll(communityIds);
            } else {
                where.append(" and rf.community_id in (null)");
            }

            String offsets = " LIMIT ? OFFSET ? ";
            //判断ID是否存在
            if (StringUtils.isNotBlank(id)) {
                where.append("  AND  r.`id` = ?  \n");
                args.add(id);
            }
            //判断小区ID是否存在
            if (StringUtils.isNotBlank(community)) {
                where.append("  AND  r.`community_id` = ?  \n");
                args.add(community);
            }

            String group = " group by r.id  ";

            // 查询总记录数
            String count = "select count(1) FROM (" + billSql + where + group + ")  c  ";
            Long total = jdbcTemplate.queryForObject(count, Long.class, args.toArray());
            LOG.info("SQL :" + billSql + where);
            if (total == 0) {
                result.setCode(StatusCode.SUCCESS_CODE_10000.getErrorCode());
                result.setMsg(StatusCode.SUCCESS_CODE_10000.getErrorMsg());
                result.setResultData(null);
                return result;
            }

            where.append(group);
            // 查询分页数据
            where.append("  ORDER BY ").append("  r.create_time desc ").append(" \n").append(offsets);
            args.add(pageSize);
            args.add(pageNumber * pageSize);
            List<Map<String, Object>> peopleList = jdbcTemplate.queryForList(billSql + where, args.toArray());

            for (Map<String, Object> map : peopleList) {
                String communityId = String.valueOf(map.get("communityId"));
                String operatorId = String.valueOf(map.get("operatorId"));
                Optional<Community> communityOptional = communityRepository.findById(communityId);
                //获取小区名称
                if (communityOptional.isPresent()) {
                    Community com = communityOptional.get();
                    map.put("communityName", com.getName());
                }
                //获取创建人名称
                User operatorUser = userRepository.findById(operatorId);
                if (operatorUser != null) {
                    map.put("operatorUserName", operatorUser.getName());
                }
            }
            //设置存储数据
            apiData.setData(peopleList);
            apiData.setTotal(total);
            LOG.info("SQL :" + billSql + where);
            result.setResultData(apiData);
        } catch (Exception e) {
            LOG.error(e.getMessage(), e);
            result.setCode(StatusCode.ERROR_CODE_10001.getErrorCode());
            result.setMsg(e.getMessage());
        }
        return result;
    }

    /*
     *账单生成-生成账单
     */
    public ResultBean<Object> createBill(String accessToken, CreateBillRequestParamVO createBillRequestParamVO) {
        LOG.info("BillService createBill accessToken={},createBillRequestParamVO={}", accessToken, createBillRequestParamVO);
        ResultBean<Object> result = new ResultBean<>();
        result.setMsg(StatusCode.SUCCESS_CODE_10000.getErrorMsg());
        result.setCode(StatusCode.SUCCESS_CODE_10000.getErrorCode());
        TokenRedisVo tokenRedisVo = redisService.findTokenVo(accessToken);
        try {
            if (tokenRedisVo == null) {
                result.setCode(StatusCode.ERROR_CODE_40001.getErrorCode());
                result.setMsg(StatusCode.ERROR_CODE_40001.getErrorMsg());
                return result;
            }
            HouseExpenseBillRuleVO houseExpenseBillRuleVO = createBillRequestParamVO.getHouseExpenseBillRuleVO();
            List<HouseExpenseRuleRefVO> houseExpenseRuleRefVOS = createBillRequestParamVO.getHouseExpenseRuleRefVOS();

            //查找是否存在收费项目，不存在则无法生成  [收费项目(1水费 2电费 3物业费 4宽带费 5电视费 6煤气费 7暖气费 8租金 9押金)]
            List<String> failRoomNumberList = new ArrayList<>(); //不存在收费项目的房号
            if (houseExpenseBillRuleVO.getChargeType() == 8 || houseExpenseBillRuleVO.getChargeType() == 9) {
                Integer chargeType = null; //收费类型：1房租 2押金
                if (houseExpenseBillRuleVO.getChargeType() == 8) {
                    chargeType = 1;
                } else {
                    chargeType = 2;
                }
                //收费项目-房租/押金账单
                for (HouseExpenseRuleRefVO vo : houseExpenseRuleRefVOS) {
                    String houseId = vo.getHouseId();
                    List<HouseExpenseRent> list = houseExpenseRentRepository.findByHouseIdAndChargeTypeAndEnableStatusAndStatus(houseId, chargeType, 1, 1);
                    if (list.size() == 0) { //不存在收费项目
                        failRoomNumberList.add(vo.getRoomNumber());
                    }
                }

            } else {

                //收费项目-其它费用设置
                for (HouseExpenseRuleRefVO vo : houseExpenseRuleRefVOS) {
                    String houseId = vo.getHouseId();
                    List<HouseExpenseHouse> list = houseExpenseHouseRepository.findByHouseId(houseId);
                    //项目费用id
                    List<String> expenseIdList = list.stream().map(HouseExpenseHouse::getExpenseId).collect(Collectors.toList());
                    //绑定房的相关类型费用
                    List<Integer> chargeTypeList = houseExpenseOtherRepository.findByIdInAndEnableStatusAndStatus(expenseIdList, 1, 1).stream().map(HouseExpenseOther::getChargeType).collect(Collectors.toList());

                    if (!chargeTypeList.contains(houseExpenseBillRuleVO.getChargeType())) {  //生成的类型不包含在收费项目里
                        failRoomNumberList.add(vo.getRoomNumber());
                    }

                }

            }
            //返回失败房号
            if (failRoomNumberList.size() > 0) {
                return ResultBean.failedResultWithMsg(failRoomNumberList.toString() + "房号不存在收费项目，无法生成账单");
            }

            if (!houseExpenseBillRuleVO.getChargeType().equals(9)) {
                for (HouseExpenseRuleRefVO houseExpenseRuleRefVO : houseExpenseRuleRefVOS) {
                    List<HouseExpenseRuleRef> existHouseExpenseRule = houseExpenseRuleRefRepository.findByHouseId(houseExpenseRuleRefVO.getHouseId());
                    for (HouseExpenseRuleRef houseExpenseRuleRef : existHouseExpenseRule) {
                        HouseExpenseBillRule houseExpenseBillRule = houseExpenseBillRuleRepository.findById(houseExpenseRuleRef.getRuleId());
                        //时间段不能有交集
                        if (houseExpenseBillRule.getChargeType().equals(houseExpenseBillRuleVO.getChargeType())) {
                            if ((houseExpenseBillRuleVO.getStartTime().getTime() < houseExpenseBillRule.getStartTime().getTime() && houseExpenseBillRuleVO.getEndTime().getTime() >= houseExpenseBillRule.getStartTime().getTime())
                                    || (houseExpenseBillRuleVO.getStartTime().getTime() >= houseExpenseBillRule.getStartTime().getTime() && houseExpenseBillRuleVO.getEndTime().getTime() <= houseExpenseBillRule.getEndTime().getTime())
                                    || (houseExpenseBillRuleVO.getStartTime().getTime() <= houseExpenseBillRule.getEndTime().getTime() && houseExpenseBillRuleVO.getEndTime().getTime() > houseExpenseBillRule.getEndTime().getTime())) {
                                return ResultBean.failedResultWithMsg("周期内账单已存在");
                            }
                        }
                    }
                }
            } else {  //押金

                for (HouseExpenseRuleRefVO houseExpenseRuleRefVO : houseExpenseRuleRefVOS) {
                    List<HouseExpenseRuleRef> existHouseExpenseRule = houseExpenseRuleRefRepository.findByHouseId(houseExpenseRuleRefVO.getHouseId());
                    for (HouseExpenseRuleRef houseExpenseRuleRef : existHouseExpenseRule) {
                        HouseExpenseBillRule houseExpenseBillRule = houseExpenseBillRuleRepository.findById(houseExpenseRuleRef.getRuleId());
                        if (houseExpenseBillRule.getChargeType().equals(houseExpenseBillRuleVO.getChargeType())) {
                            return ResultBean.failedResultWithMsg("押金账单已存在");
                        }
                    }
                }
            }
            houseExpenseBillRuleVO.setId("ZD" + KeyWorker.nextId());
            houseExpenseBillRuleVO.setNumber(houseExpenseRuleRefVOS.size());
            houseExpenseBillRuleVO.setOperatorId(tokenRedisVo.getId());
            //houseExpenseBillRuleVO.setCreateTime(new Date());
            HouseExpenseBillRule houseExpenseBillRule = new HouseExpenseBillRule();
            BeanUtils.copyProperties(houseExpenseBillRuleVO, houseExpenseBillRule);
            HouseExpenseBillRule save = houseExpenseBillRuleRepository.save(houseExpenseBillRule);
            if (save != null) {
                houseExpenseRuleRefVOS.forEach(h -> {
                    HouseExpenseRuleRef houseExpenseRuleRef = new HouseExpenseRuleRef();
                    h.setCommunityId(save.getCommunityId());
                    h.setRuleId(save.getId());
                    BeanUtils.copyProperties(h, houseExpenseRuleRef);
                    houseExpenseRuleRefRepository.save(houseExpenseRuleRef);
                });

                //
                switch (save.getChargeType()) {

                    case 1:
                        HouseExpenseWater houseExpenseWater = new HouseExpenseWater();
                        houseExpenseWater.setRuleId(save.getId());
                        houseExpenseWater.setWaterStartNum(createBillRequestParamVO.getStartNum());
                        houseExpenseWater.setWaterEndNum(createBillRequestParamVO.getEndNum());
                        houseExpenseWater.setWaterUsage(createBillRequestParamVO.getEndNum() - createBillRequestParamVO.getStartNum());
                        houseExpenseWaterRepository.save(houseExpenseWater);
                        break;
                    case 2:
                        HouseExpenseElectric houseExpenseElectric = new HouseExpenseElectric();
                        houseExpenseElectric.setRuleId(save.getId());
                        houseExpenseElectric.setElectricStartNum(createBillRequestParamVO.getStartNum());
                        houseExpenseElectric.setElectricEndNum(createBillRequestParamVO.getEndNum());
                        houseExpenseElectric.setElectricUsage(createBillRequestParamVO.getEndNum() - createBillRequestParamVO.getStartNum());
                        houseExpenseElectricRepository.save(houseExpenseElectric);
                        break;
                    case 6:
                        HouseExpenseGas houseExpenseGas = new HouseExpenseGas();
                        houseExpenseGas.setRuleId(save.getId());
                        houseExpenseGas.setGasStartNum(createBillRequestParamVO.getStartNum());
                        houseExpenseGas.setGasEndNum(createBillRequestParamVO.getEndNum());
                        houseExpenseGas.setGasUsage(createBillRequestParamVO.getEndNum() - createBillRequestParamVO.getStartNum());
                        houseExpenseGasRepository.save(houseExpenseGas);
                        break;
                }


            }
        } catch (Exception e) {
            LOG.error(e.getMessage(), e);
            result.setCode(StatusCode.ERROR_CODE_10001.getErrorCode());
            result.setMsg(e.getMessage());
        }
        return result;
    }

    /*
     *账单生成-编辑账单
     */
    public ResultBean<Object> updateBill(String accessToken, CreateBillRequestParamVO createBillRequestParamVO) {
        LOG.info("BillService updateBill accessToken={},createBillRequestParamVO={}", accessToken, createBillRequestParamVO);
        ResultBean<Object> result = new ResultBean<>();
        result.setMsg(StatusCode.SUCCESS_CODE_10000.getErrorMsg());
        result.setCode(StatusCode.SUCCESS_CODE_10000.getErrorCode());
        TokenRedisVo tokenRedisVo = redisService.findTokenVo(accessToken);
        try {
            if (tokenRedisVo == null) {
                result.setCode(StatusCode.ERROR_CODE_40001.getErrorCode());
                result.setMsg(StatusCode.ERROR_CODE_40001.getErrorMsg());
                return result;
            }
            HouseExpenseBillRuleVO houseExpenseBillRuleVO = createBillRequestParamVO.getHouseExpenseBillRuleVO();
            List<HouseExpenseRuleRefVO> houseExpenseRuleRefVOS = createBillRequestParamVO.getHouseExpenseRuleRefVOS();

            if (StringUtils.isBlank(houseExpenseBillRuleVO.getId())) {
                result.setMsg("账单id为空");
                return result;
            }

            //查找是否存在收费项目，不存在则无法生成  [收费项目(1水费 2电费 3物业费 4宽带费 5电视费 6煤气费 7暖气费 8租金 9押金)]
            List<String> failRoomNumberList = new ArrayList<>(); //不存在收费项目的房号
            if (houseExpenseBillRuleVO.getChargeType() == 8 || houseExpenseBillRuleVO.getChargeType() == 9) {
                Integer chargeType = null; //收费类型：1房租 2押金
                if (houseExpenseBillRuleVO.getChargeType() == 8) {
                    chargeType = 1;
                } else {
                    chargeType = 2;
                }
                //收费项目-房租/押金账单
                for (HouseExpenseRuleRefVO vo : houseExpenseRuleRefVOS) {
                    String houseId = vo.getHouseId();
                    List<HouseExpenseRent> list = houseExpenseRentRepository.findByHouseIdAndChargeTypeAndEnableStatusAndStatus(houseId, chargeType, 1, 1);
                    if (list.size() == 0) { //不存在收费项目
                        failRoomNumberList.add(vo.getRoomNumber());
                    }
                }

            } else {

                //收费项目-其它费用设置
                for (HouseExpenseRuleRefVO vo : houseExpenseRuleRefVOS) {
                    String houseId = vo.getHouseId();
                    List<HouseExpenseHouse> list = houseExpenseHouseRepository.findByHouseId(houseId);
                    //项目费用id
                    List<String> expenseIdList = list.stream().map(HouseExpenseHouse::getExpenseId).collect(Collectors.toList());
                    //绑定房的相关类型费用
                    List<Integer> chargeTypeList = houseExpenseOtherRepository.findByIdInAndEnableStatusAndStatus(expenseIdList, 1, 1).stream().map(HouseExpenseOther::getChargeType).collect(Collectors.toList());

                    if (!chargeTypeList.contains(houseExpenseBillRuleVO.getChargeType())) {  //生成的类型不包含在收费项目里
                        failRoomNumberList.add(vo.getRoomNumber());
                    }

                }

            }
            //返回失败房号
            if (failRoomNumberList.size() > 0) {
                return ResultBean.failedResultWithMsg(failRoomNumberList.toString() + "房号不存在收费项目，无法生成账单");
            }

            if (!houseExpenseBillRuleVO.getChargeType().equals(9)) {
                for (HouseExpenseRuleRefVO houseExpenseRuleRefVO : houseExpenseRuleRefVOS) {
                    List<HouseExpenseRuleRef> existHouseExpenseRule = houseExpenseRuleRefRepository.findByHouseId(houseExpenseRuleRefVO.getHouseId());
                    for (HouseExpenseRuleRef houseExpenseRuleRef : existHouseExpenseRule) {
                        if (houseExpenseRuleRef.getRuleId().equals(houseExpenseBillRuleVO.getId())) {
                            continue;
                        }
                        HouseExpenseBillRule houseExpenseBillRule = houseExpenseBillRuleRepository.findById(houseExpenseRuleRef.getRuleId());
                        //时间段不能有交集
                        if (houseExpenseBillRule.getChargeType().equals(houseExpenseBillRuleVO.getChargeType())) {
                            if ((houseExpenseBillRuleVO.getStartTime().getTime() < houseExpenseBillRule.getStartTime().getTime() && houseExpenseBillRuleVO.getEndTime().getTime() >= houseExpenseBillRule.getStartTime().getTime())
                                    || (houseExpenseBillRuleVO.getStartTime().getTime() >= houseExpenseBillRule.getStartTime().getTime() && houseExpenseBillRuleVO.getEndTime().getTime() <= houseExpenseBillRule.getEndTime().getTime())
                                    || (houseExpenseBillRuleVO.getStartTime().getTime() <= houseExpenseBillRule.getEndTime().getTime() && houseExpenseBillRuleVO.getEndTime().getTime() > houseExpenseBillRule.getEndTime().getTime())) {
                                return ResultBean.failedResultWithMsg("周期内账单已存在");
                            }
                        }
                    }
                }
            } else {  //押金

                for (HouseExpenseRuleRefVO houseExpenseRuleRefVO : houseExpenseRuleRefVOS) {
                    List<HouseExpenseRuleRef> existHouseExpenseRule = houseExpenseRuleRefRepository.findByHouseId(houseExpenseRuleRefVO.getHouseId());
                    for (HouseExpenseRuleRef houseExpenseRuleRef : existHouseExpenseRule) {
                        if (houseExpenseRuleRef.getRuleId().equals(houseExpenseBillRuleVO.getId())) {
                            continue;
                        }
                        HouseExpenseBillRule houseExpenseBillRule = houseExpenseBillRuleRepository.findById(houseExpenseRuleRef.getRuleId());
                        if (houseExpenseBillRule.getChargeType().equals(houseExpenseBillRuleVO.getChargeType())) {
                            return ResultBean.failedResultWithMsg("押金账单已存在");
                        }
                    }
                }
            }

            houseExpenseBillRuleRepository.deleteById(houseExpenseBillRuleVO.getId());
            houseExpenseRuleRefRepository.deleteByRuleId(houseExpenseBillRuleVO.getId());
            houseExpenseWaterRepository.deleteByRuleId(houseExpenseBillRuleVO.getId());
            houseExpenseElectricRepository.deleteByRuleId(houseExpenseBillRuleVO.getId());
            houseExpenseGasRepository.deleteByRuleId(houseExpenseBillRuleVO.getId());

            houseExpenseBillRuleVO.setId("ZD" + KeyWorker.nextId());
            houseExpenseBillRuleVO.setNumber(houseExpenseRuleRefVOS.size());
            houseExpenseBillRuleVO.setOperatorId(tokenRedisVo.getId());
            //houseExpenseBillRuleVO.setCreateTime(new Date());
            HouseExpenseBillRule houseExpenseBillRule = new HouseExpenseBillRule();
            BeanUtils.copyProperties(houseExpenseBillRuleVO, houseExpenseBillRule);
            HouseExpenseBillRule save = houseExpenseBillRuleRepository.save(houseExpenseBillRule);
            if (save != null) {
                houseExpenseRuleRefVOS.forEach(h -> {
                    HouseExpenseRuleRef houseExpenseRuleRef = new HouseExpenseRuleRef();
                    h.setCommunityId(save.getCommunityId());
                    h.setRuleId(save.getId());
                    BeanUtils.copyProperties(h, houseExpenseRuleRef);
                    houseExpenseRuleRefRepository.save(houseExpenseRuleRef);
                });

                //
                switch (save.getChargeType()) {

                    case 1:
                        HouseExpenseWater houseExpenseWater = new HouseExpenseWater();
                        houseExpenseWater.setRuleId(save.getId());
                        houseExpenseWater.setWaterStartNum(createBillRequestParamVO.getStartNum());
                        houseExpenseWater.setWaterEndNum(createBillRequestParamVO.getEndNum());
                        houseExpenseWater.setWaterUsage(createBillRequestParamVO.getEndNum() - createBillRequestParamVO.getStartNum());
                        houseExpenseWaterRepository.save(houseExpenseWater);
                        break;
                    case 2:
                        HouseExpenseElectric houseExpenseElectric = new HouseExpenseElectric();
                        houseExpenseElectric.setRuleId(save.getId());
                        houseExpenseElectric.setElectricStartNum(createBillRequestParamVO.getStartNum());
                        houseExpenseElectric.setElectricEndNum(createBillRequestParamVO.getEndNum());
                        houseExpenseElectric.setElectricUsage(createBillRequestParamVO.getEndNum() - createBillRequestParamVO.getStartNum());
                        houseExpenseElectricRepository.save(houseExpenseElectric);
                        break;
                    case 6:
                        HouseExpenseGas houseExpenseGas = new HouseExpenseGas();
                        houseExpenseGas.setRuleId(save.getId());
                        houseExpenseGas.setGasStartNum(createBillRequestParamVO.getStartNum());
                        houseExpenseGas.setGasEndNum(createBillRequestParamVO.getEndNum());
                        houseExpenseGas.setGasUsage(createBillRequestParamVO.getEndNum() - createBillRequestParamVO.getStartNum());
                        houseExpenseGasRepository.save(houseExpenseGas);
                        break;
                }


            }
        } catch (Exception e) {
            LOG.error(e.getMessage(), e);
            result.setCode(StatusCode.ERROR_CODE_10001.getErrorCode());
            result.setMsg(e.getMessage());
        }
        return result;
    }

    public ResultBean<Object> deleteBill(String accessToken, String id) {
        LOG.info("BillService deleteBill accessToken={},id={}", accessToken, id);

        if (StringUtils.isBlank(id)) {
            return ResultBean.failedResultWithMsg("账单id为空");
        }

        houseExpenseBillRuleRepository.deleteById(id);
        houseExpenseRuleRefRepository.deleteByRuleId(id);
        houseExpenseWaterRepository.deleteByRuleId(id);
        houseExpenseElectricRepository.deleteByRuleId(id);
        houseExpenseGasRepository.deleteByRuleId(id);

        return ResultBean.successfulResult(null);
    }

    public ResultBean<Object> billInfo(String accessToken, String id) {
        LOG.info("BillService billInfo accessToken={},id={}", accessToken, id);
        if (StringUtils.isBlank(id)) {
            return ResultBean.failedResultWithMsg("账单id为空");
        }
        HouseExpenseBillRule rule = houseExpenseBillRuleRepository.findById(id);
        if (rule == null) {
            return ResultBean.failedResultWithMsg("账单不存在");
        }

        HouseExpenseBillRuleVO vo = new HouseExpenseBillRuleVO();
        BeanUtils.copyProperties(rule, vo);

        //获取小区名称
        Optional<Community> communityOptional = communityRepository.findById(vo.getCommunityId());

        if (communityOptional.isPresent()) {
            vo.setCommunityName(communityOptional.get().getName());
        }

        List<HouseExpenseRuleRef> ref = houseExpenseRuleRefRepository.findByRuleId(vo.getId());
        List<HouseExpenseRuleRefVO> refVO = new ArrayList<>();
        ref.forEach(r -> {
            HouseExpenseRuleRefVO v = new HouseExpenseRuleRefVO();
            BeanUtils.copyProperties(r, v);
            refVO.add(v);
        });

        vo.setHouseExpenseRuleRefVOList(refVO);

        switch (vo.getChargeType()) {
            case 1:
                HouseExpenseWater houseExpenseWater = houseExpenseWaterRepository.findByRuleId(vo.getId());
                vo.setStartNum(houseExpenseWater.getWaterStartNum());
                vo.setEndNum(houseExpenseWater.getWaterEndNum());
                break;
            case 2:
                HouseExpenseElectric houseExpenseElectric = houseExpenseElectricRepository.findByRuleId(vo.getId());
                vo.setStartNum(houseExpenseElectric.getElectricStartNum());
                vo.setEndNum(houseExpenseElectric.getElectricEndNum());
                break;
            case 6:
                HouseExpenseGas houseExpenseGas = houseExpenseGasRepository.findByRuleId(vo.getId());
                vo.setStartNum(houseExpenseGas.getGasStartNum());
                vo.setEndNum(houseExpenseGas.getGasEndNum());
                break;
        }

        return ResultBean.successfulResult(vo);
    }

    /*
     *收费项目-租金押金设置列表展示
     */
    public ResultBean<Object> rentProjectList(String accessToken, Integer pageNumber, Integer pageSize, String id) {
        LOG.info("BillService rentProjectList accessToken={},pageNumber={},pageSize={},id={},type={}", accessToken, pageNumber, pageSize, id);
        ResultBean<Object> result = new ResultBean<>();
        result.setMsg(StatusCode.SUCCESS_CODE_10000.getErrorMsg());
        result.setCode(StatusCode.SUCCESS_CODE_10000.getErrorCode());
        TokenRedisVo tokenRedisVo = redisService.findTokenVo(accessToken);
        ApiData<Map<String, Object>> apiData = new ApiData<>();
        try {
            if (tokenRedisVo == null) {
                result.setCode(StatusCode.ERROR_CODE_40001.getErrorCode());
                result.setMsg(StatusCode.ERROR_CODE_40001.getErrorMsg());
                return result;
            }

            String billProjectSql = "select r.`id`,r.`name`,r.`charge_type` AS chargeType,r.`payment_stauts` AS paymentStauts,r.`house_id` AS houseId,\n" +
                    "r.margin_standard as marginStandard,r.`enable_status` AS enableStatus,r.`status`,r.`operator_id` AS operatorId,r.`operator_time` AS operatorTime\n" +
                    "from saas_house_expense_rent r LEFT JOIN saas_house h ON r.house_id = h.id WHERE r.status = 1 ";
            List<Object> args = new ArrayList<>();
            StringBuilder where = new StringBuilder();

            //权限过滤
            List<Map<String, Object>> communityList = appCommunityService.findCommunity(accessToken).getResultData();
            if (communityList != null && !communityList.isEmpty()) {
                where.append(" and h.residence_community_id in " + SqlUtils.foreachIn(communityList.size()));
                List<String> communityIds = communityList.stream().map(map -> {
                    String comId = map.get("communityId").toString();
                    return comId;
                }).collect(Collectors.toList());
                args.addAll(communityIds);
            } else {
                where.append(" and h.residence_community_id in (null)");
            }

            String offsets = " LIMIT ? OFFSET ? ";

            if (StringUtils.isNotBlank(id)) {
                where.append(" AND r.`id` = ?\n");
                args.add(id);
            }

            where.append(" AND r.`house_nature` = 1 \n");

            // 查询总记录数
            String count = "select count(1) FROM (" + billProjectSql + where + ")  c  ";
            Long total = jdbcTemplate.queryForObject(count, Long.class, args.toArray());

            if (total == 0) {
                result.setCode(StatusCode.SUCCESS_CODE_10000.getErrorCode());
                result.setMsg(StatusCode.SUCCESS_CODE_10000.getErrorMsg());
                result.setResultData(null);
                return result;
            }

            // 查询分页数据
            where.append(" ORDER BY ").append(" r.operator_time desc ").append(" \n").append(offsets);
            args.add(pageSize);
            args.add(pageNumber * pageSize);

            List<Map<String, Object>> peopleList = jdbcTemplate.queryForList(billProjectSql + where, args.toArray());
            for (Map<String, Object> map : peopleList) {
                String house = String.valueOf(map.get("houseId"));
                Optional<House> houseOptional = houseRepository.findById(house);
                String houseName = "";
                if (houseOptional.isPresent()) {
                    House existHouse = houseOptional.get();
                    if (existHouse != null) {
                        //获取小区名称
                        Optional<Community> communityOptional = communityRepository.findById(existHouse.getResidenceCommunityId());
                        if (communityOptional.isPresent()) {
                            Community community = communityOptional.get();
                            houseName += community.getName();
                        }
                        //获取楼栋名称
                        Optional<CommunityBuild> communityBuildOptional = communityBuildRepository.findById(existHouse.getBuildingNum());
                        if (communityBuildOptional.isPresent()) {
                            CommunityBuild communityBuild = communityBuildOptional.get();
                            houseName += communityBuild.getName() + "栋";
                        }
                        //获取单元名称
                        Optional<CommunityBuildUnit> communityBuildUnitOptional = communityBuildUnitRepository.findById(existHouse.getUnit());
                        if (communityBuildUnitOptional.isPresent()) {
                            CommunityBuildUnit communityBuildUnit = communityBuildUnitOptional.get();
                            houseName += communityBuildUnit.getName() + "单元";
                        }
                        //获取房号
                        houseName += existHouse.getRoomNumber() + "号";
                    }
                }
                map.put("houseName", houseName);
            }

            apiData.setData(peopleList);
            apiData.setTotal(total);
            result.setResultData(apiData);
        } catch (Exception e) {
            LOG.error(e.getMessage(), e);
            result.setCode(StatusCode.ERROR_CODE_10001.getErrorCode());
            result.setMsg(e.getMessage());
        }
        return result;
    }

    /*
     *收费项目-其他费用设置列表展示
     */
    public ResultBean<Object> otherProjectList(String accessToken, Integer pageNumber, Integer pageSize, String id) {
        LOG.info("BillService otherProjectList accessToken={},pageNumber={},pageSize={},id={},type={}", accessToken, pageNumber, pageSize, id);
        ResultBean<Object> result = new ResultBean<>();
        result.setMsg(StatusCode.SUCCESS_CODE_10000.getErrorMsg());
        result.setCode(StatusCode.SUCCESS_CODE_10000.getErrorCode());
        TokenRedisVo tokenRedisVo = redisService.findTokenVo(accessToken);
        ApiData<Map<String, Object>> apiData = new ApiData<>();
        try {
            if (tokenRedisVo == null) {
                result.setCode(StatusCode.ERROR_CODE_40001.getErrorCode());
                result.setMsg(StatusCode.ERROR_CODE_40001.getErrorMsg());
                return result;
            }

            String billProjectSql = " SELECT saas_house_expense_other.`id`,`name`,`charge_type` AS chargeType,`payment_stauts`  AS paymentStauts,`community_id` AS communityId,\n" +
                    "`charge_mode` AS chargeMode,`price`,`unit`,`billing_cycle_type` AS billingCycleType,`billing_cycle` AS billingCycle,\n" +
                    "`enable_status` AS enableStatus,`status`,`operator_id` AS operatorId,`operator_time` AS operatorTime \n" +
                    "FROM saas_house_expense_other left join saas_house_expense_house eh on saas_house_expense_other.`id` = eh.expense_id  WHERE status = 1   ";
            List<Object> args = new ArrayList<>();
            StringBuilder where = new StringBuilder();

            //权限过滤
            List<Map<String, Object>> communityList = appCommunityService.findCommunity(accessToken).getResultData();
            if (communityList != null && !communityList.isEmpty()) {
                where.append(" and community_id in " + SqlUtils.foreachIn(communityList.size()));
                List<String> communityIds = communityList.stream().map(map -> {
                    String comId = map.get("communityId").toString();
                    return comId;
                }).collect(Collectors.toList());
                args.addAll(communityIds);
            } else {
                where.append(" and community_id in (null)");
            }

            String offsets = " LIMIT ? OFFSET ?";

            if (StringUtils.isNotBlank(id)) {
                where.append(" AND saas_house_expense_other.`id` = ?");
                args.add(id);
            }

            String group = " group by saas_house_expense_other.id  ";

            // 查询总记录数
            String count = "select count(1) FROM (" + billProjectSql + where + group + ")  c  ";
            Long total = jdbcTemplate.queryForObject(count, Long.class, args.toArray());
            LOG.info("SQL :" + billProjectSql + where);
            if (total == 0) {
                result.setCode(StatusCode.SUCCESS_CODE_10000.getErrorCode());
                result.setMsg(StatusCode.SUCCESS_CODE_10000.getErrorMsg());
                result.setResultData(null);
                return result;
            }

            where.append(group);
            // 查询分页数据
            where.append("  ORDER BY ").append("  operator_time desc ").append(" \n").append(offsets);
            args.add(pageSize);
            args.add(pageNumber * pageSize);

            List<Map<String, Object>> peopleList = jdbcTemplate.queryForList(billProjectSql + where, args.toArray());
            for (Map<String, Object> map : peopleList) {
                String mid = (String) map.get("id");
                List<String> houseIds = houseExpenseHouseRepository.findByExpenseId(mid).stream().map(HouseExpenseHouse::getHouseId).distinct().collect(Collectors.toList());
                //房屋绑定数量
                Integer houseNumber = 0;
                if (houseIds != null) {
                    houseNumber = houseIds.size();
                }
                map.put("houseNumber", houseNumber);

                Integer price = Integer.valueOf(String.valueOf(map.get("price")));
                BigDecimal temp = new BigDecimal(price);
                map.put("price", temp != null ? temp.divide(new BigDecimal(100)) : 0.00);
                String communityId = String.valueOf(map.get("communityId"));
                //获取小区名称
                Optional<Community> communityOptional = communityRepository.findById(communityId);
                if (communityOptional.isPresent()) {
                    Community community = communityOptional.get();
                    map.put("communityName", community.getName());
                }
            }

            apiData.setData(peopleList);
            apiData.setTotal(total);
            LOG.info("SQL :" + billProjectSql + where);
            result.setResultData(apiData);
        } catch (Exception e) {
            LOG.error(e.getMessage(), e);
            result.setCode(StatusCode.ERROR_CODE_10001.getErrorCode());
            result.setMsg(e.getMessage());
        }
        return result;
    }

    /*
     *租金押金项目或其他费用项目
     *状态操作
     * status 0 禁用 1 启用 2 删除
     */
    public ResultBean<Object> changeRentOrOtherProjectStatus(String accessToken, String id, Integer status, Integer type) {
        LOG.info("BillService changeRentProjectStatus accessToken={},id={},status={},type={}", accessToken, id, status, type);
        ResultBean<Object> result = new ResultBean<>();
        result.setMsg(StatusCode.SUCCESS_CODE_10000.getErrorMsg());
        result.setCode(StatusCode.SUCCESS_CODE_10000.getErrorCode());
        TokenRedisVo tokenRedisVo = redisService.findTokenVo(accessToken);
        try {
            if (tokenRedisVo == null) {
                result.setCode(StatusCode.ERROR_CODE_40001.getErrorCode());
                result.setMsg(StatusCode.ERROR_CODE_40001.getErrorMsg());
                return result;
            }
            if (id == null || status == null || type == null) {
                result.setCode(StatusCode.ERROR_CODE_10005.getErrorCode());
                result.setMsg(StatusCode.ERROR_CODE_10005.getErrorMsg());
                return result;
            }
            if (type == 0) {
                HouseExpenseRent expenseRent = houseExpenseRentRepository.findById(id);
                if (status == 2) {
                    expenseRent.setStatus(status);
                } else {
                    if (status == 1) {
                        List<HouseExpenseRent> houseExpenseRent = houseExpenseRentRepository.findByHouseIdAndChargeTypeAndEnableStatusAndStatus(expenseRent.getHouseId(), expenseRent.getChargeType(), 1, 1);
                        if (houseExpenseRent != null && houseExpenseRent.size() > 0) {
                            return ResultBean.failedResultWithMsg("房屋此类型收费项目已有开启,更换需禁用之前收费项目再开启当前收费项目");
                        }
                    }
                    expenseRent.setEnableStatus(status);
                }
                houseExpenseRentRepository.save(expenseRent);
            } else {
                HouseExpenseOther expenseOther = houseExpenseOtherRepository.findById(id);
                if (status == 2) {
                    expenseOther.setStatus(status);
                } else {
                    if (status == 1) {
                        List<HouseExpenseOther> existHouseExpenseOther = houseExpenseOtherRepository.findByCommunityIdAndChargeTypeAndEnableStatusAndStatus(expenseOther.getCommunityId(), expenseOther.getChargeType(), 1, 1);
                        if (existHouseExpenseOther != null && existHouseExpenseOther.size() > 0) {
                            return ResultBean.failedResultWithMsg("小区此类型收费项目已有开启,更换需禁用之前收费项目再开启当前收费项目");
                        }
                    }
                    expenseOther.setEnableStatus(status);
                }
                houseExpenseOtherRepository.save(expenseOther);
            }
        } catch (Exception e) {
            LOG.error(e.getMessage(), e);
            result.setCode(StatusCode.ERROR_CODE_10001.getErrorCode());
            result.setMsg(e.getMessage());
        }
        return result;
    }

    /*
     *其他费用设置绑定房产
     */
    public ResultBean<Object> otherSetBindingHouse(String accessToken, List<BindingHouseRequestVO> bindingHouseRequestVOList) {
        LOG.info("BillService otherSetBindingHouse accessToken={},bindingHouseRequestVO={}", accessToken, bindingHouseRequestVOList);
        ResultBean<Object> result = new ResultBean<>();
        result.setMsg(StatusCode.SUCCESS_CODE_10000.getErrorMsg());
        result.setCode(StatusCode.SUCCESS_CODE_10000.getErrorCode());
        TokenRedisVo tokenRedisVo = redisService.findTokenVo(accessToken);
        try {
            if (tokenRedisVo == null) {
                result.setCode(StatusCode.ERROR_CODE_40001.getErrorCode());
                result.setMsg(StatusCode.ERROR_CODE_40001.getErrorMsg());
                return result;
            }
            if (bindingHouseRequestVOList == null) {
                result.setCode(StatusCode.ERROR_CODE_10005.getErrorCode());
                result.setMsg(StatusCode.ERROR_CODE_10005.getErrorMsg());
                return result;
            }

            for (BindingHouseRequestVO requestVO : bindingHouseRequestVOList) {
                HouseExpenseHouse expenseHouse = houseExpenseHouseRepository.findByHouseIdAndExpenseId(requestVO.getHouseId(), requestVO.getId());
                Optional<House> houseOptional = houseRepository.findById(requestVO.getHouseId());
                if (expenseHouse != null) {
                    if (houseOptional != null) {
                        House house = houseOptional.get();
                        return ResultBean.failedResultWithMsg(house.getRoomNumber() + "房已存在当前类型费用项目");
                    }
                }
            }
            for (BindingHouseRequestVO requestVO : bindingHouseRequestVOList) {
                HouseExpenseHouse houseExpenseHouse = new HouseExpenseHouse();
                houseExpenseHouse.setHouseId(requestVO.getHouseId());
                houseExpenseHouse.setExpenseId(requestVO.getId());
                houseExpenseHouse.setHouseNature(requestVO.getHouseNature());
                houseExpenseHouseRepository.save(houseExpenseHouse);
            }
        } catch (Exception e) {
            LOG.error(e.getMessage(), e);
            result.setCode(StatusCode.ERROR_CODE_10001.getErrorCode());
            result.setMsg(e.getMessage());
        }
        return result;
    }

    /*
     *新增或修改租金押金项目
     */
    public ResultBean<Object> addOrUpdateRentProject(String accessToken, List<HouseExpenseRentVO> houseExpenseRentVOList) {
        LOG.info("BillService addOrUpdateRentProject accessToken={},houseExpenseRentVO={}", accessToken, houseExpenseRentVOList);
        ResultBean<Object> result = new ResultBean<>();
        result.setMsg(StatusCode.SUCCESS_CODE_10000.getErrorMsg());
        result.setCode(StatusCode.SUCCESS_CODE_10000.getErrorCode());
        TokenRedisVo tokenRedisVo = redisService.findTokenVo(accessToken);
        try {
            if (tokenRedisVo == null) {
                result.setCode(StatusCode.ERROR_CODE_40001.getErrorCode());
                result.setMsg(StatusCode.ERROR_CODE_40001.getErrorMsg());
                return result;
            }
            if (houseExpenseRentVOList == null) {
                result.setCode(StatusCode.ERROR_CODE_10005.getErrorCode());
                result.setMsg(StatusCode.ERROR_CODE_10005.getErrorMsg());
                return result;
            }
            for (HouseExpenseRentVO houseExpenseRentVO : houseExpenseRentVOList) {
                //新增操作
                if (houseExpenseRentVO.getId() == null) {

                    List<HouseExpenseRent> houseExpenseRentList = houseExpenseRentRepository.findByHouseIdAndChargeTypeAndStatus(houseExpenseRentVO.getHouseId(),
                            houseExpenseRentVO.getChargeType(), 1);
                    if (houseExpenseRentList.size() > 0) {
                        return ResultBean.failedResultWithMsg("收费项目已存在");
                    }

                    houseExpenseRentVO.setId("PR" + KeyWorker.nextId());
                    houseExpenseRentVO.setEnableStatus(0);
                    houseExpenseRentVO.setStatus(1);
                    houseExpenseRentVO.setOperatorId(tokenRedisVo.getId());
                    houseExpenseRentVO.setOperatorTime(new Date());
                    HouseExpenseRent houseExpenseRent = new HouseExpenseRent();
                    BeanUtils.copyProperties(houseExpenseRentVO, houseExpenseRent);
                    houseExpenseRentRepository.save(houseExpenseRent);
                } else {
                    //修改操作
                    HouseExpenseRent houseExpenseRent = houseExpenseRentRepository.findById(houseExpenseRentVO.getId());

                    if (!houseExpenseRent.getHouseId().equals(houseExpenseRentVO.getHouseId())) {

                        List<HouseExpenseRent> houseExpenseRentList = houseExpenseRentRepository.findByHouseIdAndChargeTypeAndStatus(houseExpenseRentVO.getHouseId(), houseExpenseRentVO.getChargeType(), 1);
                        if (houseExpenseRentList.size() > 0) {
                            return ResultBean.failedResultWithMsg("收费项目已存在");
                        }
                    }

                    houseExpenseRent.setName(houseExpenseRentVO.getName());
                    houseExpenseRent.setPaymentStauts(houseExpenseRentVO.getPaymentStauts());
                    houseExpenseRent.setHouseId(houseExpenseRentVO.getHouseId());
                    houseExpenseRent.setOperatorId(tokenRedisVo.getId());
                    houseExpenseRent.setOperatorTime(new Date());
                    houseExpenseRent.setMarginStandard(houseExpenseRentVO.getMarginStandard() == null ? null : houseExpenseRentVO.getMarginStandard());
                    houseExpenseRentRepository.save(houseExpenseRent);
                }
            }
        } catch (Exception e) {
            LOG.error(e.getMessage(), e);
            result.setCode(StatusCode.ERROR_CODE_10001.getErrorCode());
            result.setMsg(e.getMessage());
        }
        return result;
    }

    /*
     *新增或修改其他费用项目
     */
    public ResultBean<Object> addOrUpdateOtherProject(String accessToken, HouseExpenseOtherVO houseExpenseOtherVO) {
        LOG.info("BillService addOrUpdateOtherProject accessToken={},houseExpenseOtherVO={}", accessToken, houseExpenseOtherVO);
        ResultBean<Object> result = new ResultBean<>();
        result.setMsg(StatusCode.SUCCESS_CODE_10000.getErrorMsg());
        result.setCode(StatusCode.SUCCESS_CODE_10000.getErrorCode());
        TokenRedisVo tokenRedisVo = redisService.findTokenVo(accessToken);
        try {
            if (tokenRedisVo == null) {
                result.setCode(StatusCode.ERROR_CODE_40001.getErrorCode());
                result.setMsg(StatusCode.ERROR_CODE_40001.getErrorMsg());
                return result;
            }
            if (houseExpenseOtherVO == null) {
                result.setCode(StatusCode.ERROR_CODE_10005.getErrorCode());
                result.setMsg(StatusCode.ERROR_CODE_10005.getErrorMsg());
                return result;
            }
            //新增操作
            if (houseExpenseOtherVO.getId() == null) {

                List<HouseExpenseOther> houseExpenseOtherList = houseExpenseOtherRepository.findByCommunityIdAndChargeTypeAndStatus(houseExpenseOtherVO.getCommunityId(), houseExpenseOtherVO.getChargeType(), 1);
                if (houseExpenseOtherList.size() > 0) {
                    return ResultBean.failedResultWithMsg("收费项目已存在");
                }

                houseExpenseOtherVO.setId("PO" + KeyWorker.nextId());
                houseExpenseOtherVO.setEnableStatus(0);
                houseExpenseOtherVO.setStatus(1);
                String price = yuanToFen(String.valueOf(houseExpenseOtherVO.getPrice()));
                houseExpenseOtherVO.setOperatorId(tokenRedisVo.getId());
                houseExpenseOtherVO.setOperatorTime(new Date());
                HouseExpenseOther houseExpenseOther = new HouseExpenseOther();
                houseExpenseOther.setPrice(Integer.valueOf(price));
                BeanUtils.copyProperties(houseExpenseOtherVO, houseExpenseOther);
                houseExpenseOtherRepository.save(houseExpenseOther);
            } else {
                //修改操作
                HouseExpenseOther houseExpenseOther = houseExpenseOtherRepository.findById(houseExpenseOtherVO.getId());

                if ((!houseExpenseOther.getCommunityId().equals(houseExpenseOtherVO.getCommunityId())) ||
                        (!houseExpenseOther.getChargeType().equals(houseExpenseOtherVO.getChargeType()))) {

                    List<HouseExpenseOther> houseExpenseOtherList = houseExpenseOtherRepository.findByCommunityIdAndChargeTypeAndStatus(houseExpenseOtherVO.getCommunityId(), houseExpenseOtherVO.getChargeType(), 1);
                    if (houseExpenseOtherList.size() > 0) {
                        return ResultBean.failedResultWithMsg("收费项目已存在");
                    }
                }

                houseExpenseOther.setName(houseExpenseOtherVO.getName());
                houseExpenseOther.setPaymentStauts(houseExpenseOtherVO.getPaymentStauts());
                houseExpenseOther.setChargeMode(houseExpenseOtherVO.getChargeMode());
                houseExpenseOther.setCommunityId(houseExpenseOtherVO.getCommunityId());
                String price = yuanToFen(String.valueOf(houseExpenseOtherVO.getPrice()));
                houseExpenseOther.setPrice(Integer.valueOf(price));
                houseExpenseOther.setUnit(houseExpenseOtherVO.getUnit());
                houseExpenseOther.setBillingCycleType(houseExpenseOtherVO.getBillingCycleType());
                houseExpenseOther.setBillingCycle(houseExpenseOtherVO.getBillingCycle());
                houseExpenseOther.setOperatorId(tokenRedisVo.getId());
                houseExpenseOther.setOperatorTime(new Date());
                houseExpenseOtherRepository.save(houseExpenseOther);
            }
        } catch (Exception e) {
            LOG.error(e.getMessage(), e);
            result.setCode(StatusCode.ERROR_CODE_10001.getErrorCode());
            result.setMsg(e.getMessage());
        }
        return result;
    }

    /*
     *查询所有小区
     */
    public ResultBean<Object> communityList(String accessToken) {
        LOG.info("BillService communityList accessToken={}", accessToken);
        ResultBean<Object> result = new ResultBean<>();
        result.setMsg(StatusCode.SUCCESS_CODE_10000.getErrorMsg());
        result.setCode(StatusCode.SUCCESS_CODE_10000.getErrorCode());
        TokenRedisVo tokenRedisVo = redisService.findTokenVo(accessToken);
        try {
            //权限鉴定
            if (tokenRedisVo == null) {
                result.setCode(StatusCode.ERROR_CODE_40001.getErrorCode());
                result.setMsg(StatusCode.ERROR_CODE_40001.getErrorMsg());
                return result;
            }
            //查询所有小区数据
            List<Community> all = communityRepository.findAll();
            result.setResultData(all);
        } catch (Exception e) {
            LOG.error(e.getMessage(), e);
            result.setCode(StatusCode.ERROR_CODE_10001.getErrorCode());
            result.setMsg(e.getMessage());
        }
        return result;
    }

    public ResultBean<Object> findBindingHouse(String accessToken, String id) {
        try {
            if (StringUtils.isBlank(id)) {
                return ResultBean.failedResultOfParamWithMsg("项目id为空");
            }

            List<String> houseIds = houseExpenseHouseRepository.findByExpenseId(id).stream()
                    .map(HouseExpenseHouse::getHouseId).distinct().collect(Collectors.toList());

            return ResultBean.successfulResult(houseIds);
        } catch (Exception e) {
            LOG.error(e.getMessage(), e);
            return ResultBean.failedResultOfException();
        }
    }


}
